#ifndef COMMON_UTILS_HPP
#define COMMON_UTILS_HPP

#include <chrono>

#define SET_RANGE(var, min, max)       \
    {                                  \
        var = (var > min) ? var : min; \
        var = (var < max) ? var : max; \
    }

class CpsTimer
{
public:
    CpsTimer()
    {
        start();
        for (int i = 0; i < CPS_NUM; ++i)
        {
            lastCps[i] = 0;
        }
    }

    void start()
    {
        time_start = std::chrono::steady_clock::now();
        time_end = time_start;
    }

    void end()
    {
        time_end = std::chrono::steady_clock::now();
    }

    int getDurationMs() const
    {
        return int(std::chrono::duration_cast<std::chrono::milliseconds>(time_end - time_start).count());
    }

    int getCurCps() const
    {
        return (1000 / getDurationMs());
    }

    float getAvgCps()
    {
        end();

        int curCps = getCurCps();
        int avgCps = 0;
        for (int i = 0; i < CPS_NUM; ++i)
        {
            lastCps[i] = (i == CPS_NUM - 1) ? curCps : lastCps[i + 1];
            avgCps += lastCps[i];
        }

        start();

        return ((float)avgCps / CPS_NUM);
    }

private:
    std::chrono::steady_clock::time_point time_start;
    std::chrono::steady_clock::time_point time_end;
    static const int CPS_NUM = 30;
    int lastCps[CPS_NUM];
};

#endif